package com.ssy.lingxi.settle.accounts.serviceimpl;

import com.ssy.lingxi.common.constant.basic.PurchaseContractPayTypeEnum;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.dto.request.SettlementOrderVO;
import com.ssy.lingxi.settle.accounts.entity.SettlementOrderDO;
import com.ssy.lingxi.settle.accounts.entity.SettlementProductDO;
import com.ssy.lingxi.settle.accounts.model.constant.SettleAccountsServiceContants;
import com.ssy.lingxi.settle.accounts.repository.SettlementOrderRepository;
import com.ssy.lingxi.settle.accounts.service.ISettlementOrderService;
import com.ssy.lingxi.settle.accounts.utils.NumberUtil;
import com.ssy.lingxi.settle.accounts.utils.OrderDateTimeUtil;
import com.ssy.lingxi.settle.accounts.utils.SerialNumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 结算待对账订单信息接口接口实现
 * @author Saske
 * @date 2021/12/16
 * @version 2.0.0
 */
@Service
public class SettlementOrderServiceImpl implements ISettlementOrderService {

    private final static Logger logger = LoggerFactory.getLogger(SettlementOrderServiceImpl.class);

    @Resource
    private SettlementOrderRepository orderRepository;

    /**
     * 新增结算待对账单订单信息
     * @author Saske
     * @date 2021/12/8
     * @return 结算待对账单订单id
     **/
    @Override
    @Transactional(rollbackFor = BusinessException.class)
    public Wrapper<Void> save(SettlementOrderVO saveVo) {
        SettlementOrderDO entity = new SettlementOrderDO();
        entity.setBillId(saveVo.getBillId());
        entity.setBillNo(saveVo.getBillNo());
        // 设置单据总额
        entity.setBillAmount(saveVo.getBillAmount());
        // 设置单据日期
        LocalDateTime billDate = OrderDateTimeUtil.timestampToLocalDateTime(saveVo.getBillDate());
        entity.setBillDate(billDate);
        // 设置单据摘要
        entity.setBillAbstract(saveVo.getBillAbstract());
        // 设置来源合同
        entity.setSourceContractId(saveVo.getSourceContractId());
        entity.setBuyerMemberId(saveVo.getBuyerMemberId());
        entity.setBuyerRoleId(saveVo.getBuyerRoleId());
        entity.setVendorMemberId(saveVo.getVendorMemberId());
        entity.setVendorRoleId(saveVo.getVendorRoleId());
        entity.setPayee(saveVo.getPayee());
        entity.setPayer(saveVo.getPayer());
        entity.setDeliveryBatch(saveVo.getDeliveryBatch());
        entity.setDeliveryNo(saveVo.getDeliveryNo());
        LocalDateTime deliveryTime =OrderDateTimeUtil.timestampToLocalDateTime(saveVo.getDeliveryTime());
        entity.setDeliveryTime(deliveryTime);
        entity.setReceiveNo(saveVo.getReceiveNo());
        LocalDateTime receiveTime =OrderDateTimeUtil.timestampToLocalDateTime(saveVo.getReceiveTime());
        entity.setReceiveTime(receiveTime);
        entity.setOrderStatus(saveVo.getOrderStatus());
        entity.setOrderType(saveVo.getOrderType());
        entity.setBillType(saveVo.getBillType());

        List<SettlementProductDO> productList = saveVo.getProducts().stream().map( r-> {
            SettlementProductDO productDO = new SettlementProductDO();
            productDO.setPayWay(r.getPayWay());
            productDO.setPayMonth(r.getPayMonth());
            productDO.setPayDate(r.getPayDate());
            //如果没有结算方式，或者结算方式为现结，则结算时间为当前收货时间
            if (NumberUtil.isNullOrNegative(r.getPayWay()) || r.getPayWay().equals(PurchaseContractPayTypeEnum.CASH.getCode())){
                productDO.setExpectPayTime(receiveTime);
            }
            //如果结算方式为账期（按天），则结算时间为当前收货时间+天
            else if (r.getPayWay().equals(PurchaseContractPayTypeEnum.PERIOD_DAILY.getCode())){
                productDO.setExpectPayTime(receiveTime.plusDays(r.getPayDate().longValue()));
            }
            //如果结算方式为账期（按月）或 结算方式为月结+结算日
            else if (r.getPayWay().equals(PurchaseContractPayTypeEnum.PERIOD_MONTHLY.getCode()) || r.getPayWay().equals(PurchaseContractPayTypeEnum.MONTHLY.getCode())){
                productDO.setExpectPayTime(calculationDate(r.getPayWay(),r.getPayMonth(),r.getPayDate(),receiveTime));
            }
            productDO.setProductNo(r.getProductNo());
            productDO.setName(r.getName());
            productDO.setSpec(r.getSpec());
            productDO.setCategory(r.getCategory());
            productDO.setBrand(r.getBrand());
            productDO.setUnit(r.getUnit());
            productDO.setTaxRate(r.getTaxRate());
            productDO.setPrice(r.getPrice());
            productDO.setReceiveQuantity(r.getReceiveQuantity());
            productDO.setReconciledQuantity(BigDecimal.ZERO);
            productDO.setReconciledMoney(BigDecimal.ZERO);
            productDO.setReconciliationQuantity(r.getReceiveQuantity());
            productDO.setOrder(entity);
            return productDO;
        }).collect(Collectors.toList());
        entity.setProducts(productList);

        orderRepository.saveAndFlush(entity);
        return Wrapper.success();
    }

//    /**
//     * 根据单据ID查询当前订单的单据总金额
//     * @param billId   单据ID
//     */
//    @Override
//    public BigDecimal getTotalMoneyAmount(Long billId) {
//
//        SettlementOrderDO entity = orderRepository.findByBillId(billId);
//        if (entity == null) {
//            return BigDecimal.ZERO;
//        }
//
//        return CollectionUtils.isEmpty(entity.getProducts()) ? BigDecimal.ZERO : entity.getProducts().stream().map(p -> p.getPrice().multiply(p.getReceiveQuantity())).reduce(BigDecimal.ZERO,BigDecimal::add);
//    }



    /**
     * 新增待对账单订单商品数据通知
     * @param jsonMessage 从消息队列中接收到的消息（订单信息和商品明细信息）
     */
    @Override
    public void saveToBeReconciliation(String jsonMessage) {

        logger.info("接收到MQ待对账单订单商品信息 =>" +jsonMessage);

        SettlementOrderVO settlementOrder = SerialNumberUtils.deserializeObject(jsonMessage, SettlementOrderVO.class);
        if (settlementOrder == null ){
            logger.error("请款：" + jsonMessage);
            return;
        }

        Wrapper<Void> result = this.save(settlementOrder);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            logger.info("保存待对账单订单商品信息错误 => orderNo:" + settlementOrder.getBillNo() + ", code:" + result.getCode() + ", msg:" + result.getMessage());
        }

    }

    /**
     * 根据结算方式，计算结算日期
     * @param payWay 结算方式，payMonth结算方式-月，payDay结算方式-日，dateTime收货时间
     * @return 结算日期
     */
    private static LocalDateTime calculationDate(Integer payWay , Integer payMonth , Integer payDay , LocalDateTime dateTime){

        String[] split = dateTime.format(SettleAccountsServiceContants.DEFAULT_DATE_FORMATTER).split("-");
        Integer year = Integer.valueOf(split[0]);
        Integer month = Integer.valueOf(split[1]);
        Integer day = Integer.valueOf(split[2]);

        LocalDateTime expectPayTime = null;

        ////如果结算方式为月结+结算日，则收货日期下个月的结算日为预计结算日期
        if (payWay.equals(PurchaseContractPayTypeEnum.MONTHLY.getCode())){
            if(month + 1 > 13){
                expectPayTime = LocalDateTime.of(year+1 ,1,payDay,0,0);
            }else {
                expectPayTime = LocalDateTime.of(year,month+1,payDay,0,0);
            }
        }
        //如果结算方式为账期（按月）
        else if (payWay.equals(PurchaseContractPayTypeEnum.PERIOD_MONTHLY.getCode())){

            Integer y = (month + payMonth) / 12;
            int m = (month + payMonth) % 12;

            // 收货日小于或等于结算日
            if (day < payDay || day.equals(payDay)){
                // 收货月不超过本年
                if (month + payMonth < 13){
                    LocalDateTime helpDateTime = LocalDateTime.of(year + y, month + payMonth, 1, 0, 0);
                    // 获取当月最大天数
                    int maxMonth = helpDateTime.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                    int targetMonth =  maxMonth < payDay ? maxMonth : payDay;
                    expectPayTime = LocalDateTime.of(year+y,month+payMonth,targetMonth,0,0);
                }
                // 收货月超过本年
                else if (month + payMonth > 13){
                    LocalDateTime helpDateTime = LocalDateTime.of(year + y, month + payMonth, 1, 0, 0);
                    // 获取当月最大天数
                    int maxMonth = helpDateTime.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
                    int targetMonth =  maxMonth < payDay ? maxMonth : payDay;
                    expectPayTime = LocalDateTime.of(year+y,m,targetMonth,0,0);
                }
            }
            //收货日大于结算日
            else {
                // 收货月不超过本年
                if (month + payMonth + 1 < 13){
                    expectPayTime = LocalDateTime.of(year+y,month+payMonth+1,payDay,0,0);
                }
                // 收货月超过本年
                else if (month + payMonth + 1 > 13){
                    expectPayTime = LocalDateTime.of(year+y,m+1,payDay,0,0);
                }
            }
        }
        return expectPayTime;
    }

}
